package com.uvt.agenda;

import com.uvt.agenda.database.DatabaseManager;
import com.uvt.agenda.iterator.EIterator;
import com.uvt.agenda.iterator.EventsContainer;
import org.joda.time.DateTime;

import java.util.ArrayList;

/**
 * Created by Cristian Holdunu on 22/01/14.
 * 01:12
 */
public class EventsProvider implements EObservable{
    private EventsContainer eventsContainer;
//    private ArrayList<Event> events;
    private static EventsProvider instance;
    private DatabaseManager dbManager;
    private ArrayList<EObserver> observers = new ArrayList<EObserver>();
    private Event dummyEvent = new Event();


    /**
     * Private constructor, used only in getInstance.
     * @param dbm DatabaseManager
     */
    private EventsProvider(DatabaseManager dbm) {
        this.dbManager = dbm;
        eventsContainer = new EventsContainer(dbm.getAllEvents());
    }

    public static EventsProvider getInstance(){
        if (instance == null) {
            try {
                DatabaseManager dbm = AndroidUtils.getDbManager();
                if (dbm != null) {
                    instance = new EventsProvider(AndroidUtils.getDbManager());
                } else {
                    throw (new Exception("Null database manager"));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return instance;
    }
//
//    public ArrayList<Event> getAllEvents() {
//        if (events == null || events.size() == 0 ) {
//            this.events = dbManager.getAllEvents();
//        }
//        try{
//            int year = DateTime.now().getYear();
//            ArrayList<Event> holidays = CheckHolidays.getHolidaysEvents(year);
//            this.events.addAll(holidays);
//        }
//        catch(Exception e){
//            e.printStackTrace();
//        }
//        return this.events;
//    }

    public EventsContainer getAllEvents() {
        if (eventsContainer == null || eventsContainer.size() == 0) {
            this.eventsContainer = new EventsContainer(dbManager.getAllEvents());
        }
        try{
            int year = DateTime.now().getYear();
            ArrayList<Event> holidays = CheckHolidays.getHolidaysEvents(year);
            this.eventsContainer.addEvents(holidays);
        }
        catch(Exception e){
            //skip..
        }
        return this.eventsContainer;
    }

    public EventsContainer getEventsFor(int year, int month, int day) {
        EventsContainer ec = new EventsContainer();
        EIterator iterator = eventsContainer.getIterator();

        while (iterator.hasNext()) {
            Event event = iterator.next();
            if (event.getStartDateTime().getYear() == year &&
                    event.getStartDateTime().getMonthOfYear() == month &&
                    event.getStartDateTime().getDayOfMonth() == day) {
                ec.add(event);
            }
        }
        try{
            ArrayList<Event> holidays = CheckHolidays.getHolidaysEvents(year,month,day);
            ec.addEvents(holidays);
        }
        catch(Exception e){
            e.printStackTrace();
        }
        return ec;

    }

    public EventsContainer getEventsFor(int year, int month) {
        EventsContainer ec = new EventsContainer();
        EIterator iterator = eventsContainer.getIterator();

        while (iterator.hasNext()) {
            Event event = iterator.next();
            if (event.getStartDateTime().getYear() == year &&
                    event.getStartDateTime().getMonthOfYear() == month) {
                ec.add(event);
            }
        }
        try{
            ArrayList<Event> holidays = CheckHolidays.getHolidaysEvents(year,month);
            ec.addEvents(holidays);
        }
        catch(Exception e){
            e.printStackTrace();
        }
        return ec;

    }


    public EventsContainer getEventsFor(int year) {
        EventsContainer ec = new EventsContainer();
        EIterator iterator = eventsContainer.getIterator();

        while (iterator.hasNext()) {
            Event event = iterator.next();
            if (event.getStartDateTime().getYear() == year) {
                ec.add(event);
            }
        }
        try{
            ArrayList<Event> holidays = CheckHolidays.getHolidaysEvents(year);
            ec.addEvents(holidays);
        }
        catch(Exception e){
            e.printStackTrace();
        }
        return ec;

    }


//    public ArrayList<Event> getEventsFor(int year, int month, int day) {
//        ArrayList<Event> events = new ArrayList<Event>();
//
//        for (Event event: this.events){
//            if (event.getStartDateTime().getYear() == year &&
//                    event.getStartDateTime().getMonthOfYear() == month &&
//                    event.getStartDateTime().getDayOfMonth() == day) {
//                events.add(event);
//            }
//        }
//        try{
//            ArrayList<Event> holidays = CheckHolidays.getHolidaysEvents(year,month,day);
//            events.addAll(holidays);
//        }
//        catch(Exception e){
//            //skip..
//        }
//
//        return events;
//    }

//
//    public ArrayList<Event> getEventsFor(int year, int month) {
//        ArrayList<Event> events = new ArrayList<Event>();
//        for (Event event: this.events){
//            if (event.getStartDateTime().getYear() == year &&
//                    event.getStartDateTime().getMonthOfYear() == month) {
//                events.add(event);
//            }
//        }
//        try{
//            ArrayList<Event> holidays = CheckHolidays.getHolidaysEvents(year,month);
//            events.addAll(holidays);
//        }
//        catch(Exception e){
//            //skip..
//        }
//
//        return events;
//    }
//
//    public ArrayList<Event> getEventsFor(int year) {
//        ArrayList<Event> events = new ArrayList<Event>();
//        for (Event event: this.events){
//            if (event.getStartDateTime().getYear() == year) {
//                events.add(event);
//            }
//        }
//        try{
//            ArrayList<Event> holidays = CheckHolidays.getHolidaysEvents(year);
//            events.addAll(holidays);
//        }
//        catch(Exception e){
//            //skip..
//        }
//
//        return events;
//    }

    public short[] getWeekFlags (int weekNumber) {
        short weekFlags[] = new short[8];
        if (eventsContainer == null || eventsContainer.size() == 0)
            getAllEvents();

        EIterator iterator = eventsContainer.getIterator();
        while (iterator.hasNext()) {
            Event nextEvent = iterator.next();
            if (nextEvent.getWeekOfYear() == weekNumber) {

                weekFlags[nextEvent.getStartDateTime().dayOfWeek().get()]++;
            }
        }
        // Get the events for week @weekNumber
        return weekFlags;
    }

    @Override
    public void addObserver(EObserver observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(EObserver observer) {
        if (observers.contains(observer))
            observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (EObserver observer: observers)
            observer.update(this);
    }

    public void addNewEvent(Event event) {
        eventsContainer.add(event);
        dbManager.saveNewEvent(event);
        notifyObservers();
    }

    public void deleteEvent(Event event) {
        dbManager.deleteEvent(event);
        eventsContainer.removeEvent(event);
        notifyObservers();
    }

    public void updateEvent(Event event) {
        dbManager.updateEvent(event);
        notifyObservers();

    }
}
